/**
 *******************************************************************************
 * @FileName  : ccm.h
 * @Author    : GaoQiu
 * @CreateDate: 2020-05-18
 * @Copyright : Copyright(C) GaoQiu
 *              All Rights Reserved.
 *******************************************************************************
 *
 * The information contained herein is confidential and proprietary property of
 * GaoQiu and is available under the terms of Commercial License Agreement
 * between GaoQiu and the licensee in separate contract or the terms described
 * here-in.
 *
 * This heading MUST NOT be removed from this file.
 *
 * Licensees are granted free, non-transferable use of the information in this
 * file under Mutual Non-Disclosure Agreement. NO WARRENTY of ANY KIND is provided.
 *
 *******************************************************************************
 */

#ifndef CCM_H_
#define CCM_H_

#include "stack/ble_config.h"

/*! CCM error code */
enum{
	CCM_SUCCESS           = 0,
	CCM_ERR_INVALID_PARAM = 1,
	CCM_ERR_CBC_MAC_FAIL  = 2,
	CCM_ERR_CTR_MODE_FAIL = 3,
	CCM_ERR_MAC_FAIL      = 4,
};

#define ZERO_BYTE                0x00

/*! max additional authenticated size in bytes: 2^16 - 2^8 = 65280 */
#define CCM_AAD_MAX_BYTES        0xff00

/*! max message size in bytes: 2^(8L) = 2^16 = 65536 */
#define CCM_PAYLOAD_MAX_BYTES    0x10000

/*! CCM context type */
typedef struct{
	uint8_t  *key;    /*!< AES key */
	uint8_t  *nonce;  /*!< nonce value, the length is 13. */
	uint8_t   mLen;   /*!< MAC length in bytes (parameter t in SP-800 38C). 4,6,8,10,12,14,16 */
}ccm_ctx_t;


/**
 * @brief : CCM context initialzation.
 *
 * @param : pCtx       Pointer to CCM context structure.
 * @param : key        Pointer to key memory.
 * @param : kLen       length of key.
 * @param : nonce      Pointer to Nonce memory.
 * @param : nLen       length of nonce.
 * @param : mLen       length if MAC.
 *
 * @return: CCM_SUCCESS if ok. others value if fail
 */
int ccm_initContext(ccm_ctx_t *pCtx, uint8_t *key, uint32_t kLen, uint8_t *nonce, uint32_t nLen, uint8_t mLen);

/**
 * @brief : CCM encrypt and authenticate.
 *
 * @param : out        Pointer to out memory.
 * @param : oLen       length of data   (must: oLen >= pLen + macLen).
 * @param : aad        Pointer to additional authenticate data memory.
 * @param : aLen       length of data.  (must: aLen < CCM_AAD_MAX_BYTES)
 * @param : payload    Pointer to payload memory.
 * @param : pLen       length of data.  (must: pLen < CCM_PAYLOAD_MAX_BYTES)
 * @param : pCtx       Pointer to CCM context structure.
 *
 * @return: CCM_SUCCESS if ok. others value if fail
 */
int ccm_encryptAuth(uint8_t *out, uint32_t oLen, const uint8_t *aad, uint32_t aLen,
		            const uint8_t *payload, uint32_t pLen, ccm_ctx_t *pCtx);

/**
 * @brief : CCM decrypt and authenticate.
 *
 * @param : out        Pointer to out memory.
 * @param : oLen       length of data   (must: oLen >= pLen - macLen).
 * @param : aad        Pointer to additional authenticate data memory.
 * @param : aLen       length of data.  (must: aLen < CCM_AAD_MAX_BYTES)
 * @param : payload    Pointer to payload memory. (must: contain MAC)
 * @param : pLen       length of data.  (must: pLen < CCM_PAYLOAD_MAX_BYTES)
 * @param : pCtx       Pointer to CCM context structure.
 *
 * @return: CCM_SUCCESS if ok. others value if fail
 */
int ccm_decryptAuth(uint8_t *out, uint32_t oLen, const uint8_t *aad, uint32_t aLen,
		            const uint8_t *payload, uint32_t pLen, ccm_ctx_t *pCtx);

#endif /* CCM_H_ */
